﻿#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WinSock2.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <easyx.h> 
#include <conio.h> 
#include <graphics.h> 
#include <iostream> 
#include <fstream> 
#include <string.h> 
using namespace std;

#pragma comment(lib,"ws2_32.lib")
#define RECV_OVER 1
#define RECV_YET 0
char userName[16] = { 0 };
char chatName[16] = { 0 };
int  c_char = 0;
char groupName[16] = { 0 };
int iStatus = RECV_YET;
const char cgroup[16] = "#2";
const char cone[16] = "#1";
WSADATA wsaData = { 0 };//存放套接字信息
SOCKET ClientSocket = INVALID_SOCKET;//客户端套接字
SOCKADDR_IN ServerAddr = { 0 };//服务端地址
USHORT uPort = 9986;//服务端端口
//接受数据
unsigned __stdcall ThreadRecv(void* param)
{
	char buf[128] = { 0 };
	while (1)
	{
		int ret = recv(*(SOCKET*)param, buf, sizeof(buf), 0);
		if (ret == SOCKET_ERROR)
		{
			Sleep(500);
			continue;
		}
		if (strlen(buf) != 0)
		{
			printf("%s\n", buf);
			iStatus = RECV_OVER;
		}
		else
			Sleep(100);
	}
	return 0;
}

//发送数据
unsigned __stdcall ThreadSend(void* param)
{
	char buf[128] = { 0 };
	int ret = 0;
	while (1)
	{
		int c = getch();
		if (c == 27)   //ESC ASCII是27
		{
			printf("输入1私聊\n输入2群聊\n");
			scanf("输入你的选择:%d", &c_char);
			if (c_char == 1) {
				memset(buf, 0, sizeof(buf));
				printf("请输入想私聊的对象的用户名:");
				gets_s(buf);
				strcat(buf, cone);
				char b[17] = { 0 };
				sprintf(b, "#%s", buf);
				ret = send(*(SOCKET*)param, b, sizeof(b), 0);
				if (ret == SOCKET_ERROR)
					return 1;
				continue;
			}
			else if (c_char == 2) {
				memset(buf, 0, sizeof(buf));
				printf("请输入想要加入的群聊:");
				gets_s(buf);
				strcat(buf, cgroup);
				char b[17] = { 0 };
				sprintf(b, "#%s", buf);
				ret = send(*(SOCKET*)param, b, sizeof(b), 0);
				if (ret == SOCKET_ERROR)
					return 1;
				_beginthreadex(NULL, 0, ThreadSendGroup, &ClientSocket, 0, NULL);
				return 0;
			}
		}
		if (c == 72 || c == 0 || c == 68)//加一个无回显的读取字符函数
			continue;
		printf("%s: ", userName);
		gets_s(buf);
		ret = send(*(SOCKET*)param, buf, sizeof(buf), 0);
		if (ret == SOCKET_ERROR)
			return 1;
	}
	return 0;
}
//群聊发送数据
unsigned __stdcall ThreadSendGroup(void* param)
{
	char buf[128] = { 0 };
	int ret = 0;
	while (1)
	{
		int c = getch();
		if (c == 27)   //ESC ASCII是27
		{
			printf("输入1私聊\n输入2群聊\n");
			scanf("输入你的选择:%d", &c_char);
			if (c_char == 1) {
				memset(buf, 0, sizeof(buf));
				printf("请输入想私聊的对象的用户名:");
				gets_s(buf);
				strcat(buf, cone);
				char b[17] = { 0 };
				sprintf(b, "#%s", buf);
				ret = send(*(SOCKET*)param, b, sizeof(b), 0);
				if (ret == SOCKET_ERROR)
					return 1;
				_beginthreadex(NULL, 0, ThreadSend, &ClientSocket, 0, NULL); //启动私聊线程
				return 0; //关闭群聊线程
			}
			else if (c_char == 2) {
				memset(buf, 0, sizeof(buf));
				printf("请输入想要加入的群聊:");
				gets_s(buf);
				strcat(buf, cgroup);
				char b[17] = { 0 };
				sprintf(b, "#%s", buf);
				ret = send(*(SOCKET*)param, b, sizeof(b), 0);
				if (ret == SOCKET_ERROR)
					return 1;
				continue;
			}
			
		}
		if (c == 72 || c == 0 || c == 68)//加一个无回显的读取字符函数
			continue;
		printf("%s: ", userName);
		gets_s(buf);
		ret = send(*(SOCKET*)param, buf, sizeof(buf), 0);
		if (ret == SOCKET_ERROR)
			return 1;
	}
	return 0;
}
//连接服务器
int ConnectServer()
{
	//初始化套接字
	if (WSAStartup(MAKEWORD(2, 2), &wsaData))
	{
		printf("WSAStartup错误代码: %d\n", WSAGetLastError());
		return -1;
	}
	//创建套接字
	ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (ClientSocket == INVALID_SOCKET)
	{
		printf("socket错误代码: %d\n", WSAGetLastError());
		return -1;
	}
	//输入服务器IP
	printf("请输入服务器的IP地址:");
	char IP[32] = { 0 };
	gets_s(IP);
	//设置服务器地址
	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_port = htons(uPort);//服务器端口
	ServerAddr.sin_addr.S_un.S_addr = inet_addr(IP);//服务器地址

	printf("等待连接中，请稍等(时间过长无显示请换IP地址输入)......\n");
	//连接服务器
	if (SOCKET_ERROR == connect(ClientSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr)))
	{
		printf("connect错误代码: %d\n", WSAGetLastError());
		closesocket(ClientSocket);
		WSACleanup();
		return -1;
	}
	printf("连接成功--->>> IP:%s Port:%d\n",IP, htons(ServerAddr.sin_port));
	printf("请输入您的用户名: ");
	gets_s(userName);
	send(ClientSocket, userName, sizeof(userName), 0);

	printf("输入1私聊\n输入2群聊\n");
	scanf("输入你的选择:%d",&c_char);
	if (c_char == 1) {
		printf("请输入想要私聊的对象的用户名: ");
		gets_s(chatName);
		strcat(chatName, cone);
		send(ClientSocket, chatName, sizeof(chatName), 0);
		printf("\n\n");

		_beginthreadex(NULL, 0, ThreadRecv, &ClientSocket, 0, NULL); //启动接收和发送消息线程
		_beginthreadex(NULL, 0, ThreadSend, &ClientSocket, 0, NULL);
	}
	else if (c_char == 2) {
		printf("请输入想要加入群聊的名称:");
		gets_s(groupName);
		strcat(groupName,cgroup);
		send(ClientSocket, groupName, sizeof(groupName), 0);
		printf("\n\n");
		_beginthreadex(NULL, 0, ThreadRecv, &ClientSocket, 0, NULL); //启动接收和发送消息线程
		_beginthreadex(NULL, 0, ThreadSendGroup, &ClientSocket, 0, NULL);
	}
	for (int k = 0; k < 1000; k++)
		Sleep(10000000);
	closesocket(ClientSocket);
	WSACleanup();
	return 0;
}
int main()
{
	IMAGE word1;
	initgraph(800, 600);//初始化 800*600 的软件界面 
	//loadimage(&word1, "images\\tupian.jpg", 800, 600);
	//putimage(0, 0, &word1);
	setbkmode(TRANSPARENT);	//清除背景色
	settextcolor(YELLOW);
	settextstyle(50, 0, _T("黑体"));
	outtextxy(200, 100, _T("欢迎使用聊天系统"));
	outtextxy(320, 150, _T("请稍候"));
	setcolor(WHITE);//显示信息字体颜色为黄色，亮一些
	settextstyle(20, 0, _T("黑体"));
	outtextxy(300, 320, _T("学校：湖北工业大学"));
	outtextxy(300, 340, _T("专业：数据科学与大数据技术"));
	outtextxy(300, 360, _T("学号：2110311110"));
	outtextxy(300, 380, _T("学生姓名：杨佳杰"));
	outtextxy(300, 400, _T("学号：2110311106"));
	outtextxy(300, 420, _T("学生姓名：刘肇胤"));
	outtextxy(300, 440, _T("学号：2110311107"));
	outtextxy(300, 460, _T("学生姓名：谭俊熙"));
	_sleep(6000);
	cleardevice();
	closegraph();
	ConnectServer(); //连接服务器
	return 0;
}

